package com.holly.unit.bpmn.modular.activiti.controller;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.holly.unit.bpmn.activiti.ActivitiOperator;
import com.holly.unit.bpmn.activiti.pojo.ActiviModelListRequest;
import com.holly.unit.bpmn.activiti.pojo.ActivitiModelInfo;
import com.holly.unit.bpmn.activiti.pojo.BpmnModelTreeNode;
import com.holly.unit.bpmn.activiti.pojo.NewModelRequest;
import com.holly.unit.bpmn.api.util.NetWorkUtil;
import com.holly.unit.core.pojo.response.ErrorResponseData;
import com.holly.unit.core.pojo.response.ResponseData;
import com.holly.unit.core.pojo.response.SuccessResponseData;
import com.holly.unit.db.api.pojo.page.PageResult;
import com.holly.unit.scanner.api.annotation.ApiResource;
import com.holly.unit.scanner.api.annotation.GetResource;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.repository.Model;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

/**
 * 类描述: 工作流Activiti集成在线页面绘制工具API
 *
 * @author fxr
 * @version 1.0.0
 * @date 2022/2/8 14:37R
 */
@RestController
@ApiResource(name = "网页流程编辑器元素")
@Api(tags = "网页流程编辑器元素API")
@RequestMapping("activiti/activitiService")
@Slf4j
public class ActivitCoreController {

    @Value("${server.servlet.context-path}")
    private String contentPath;

    @Value("${server.port}")
    private String port;

    @Resource
    private ActivitiOperator operator;

    @ApiOperation(value = "BPMN 2.0标准工具" ,notes = "BPMN 2.0标准工具")
    @RequestMapping(value="/editor/stencilset", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
    public String getStencilset() {
        InputStream stencilsetStream = this.getClass()
                .getClassLoader()
                .getResourceAsStream("static/activiti/stencilset.json");
        try {
            return IOUtils.toString(stencilsetStream, "utf-8");
        } catch (Exception e) {
            throw new ActivitiException("Error while loading stencil set", e);
        }
    }

    @RequestMapping(value="/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json")
    public ObjectNode getEditorJson(@PathVariable String modelId) {
        return operator.getEditorJson(modelId);
    }

    /***
     * 流程模型信息保存
     * @param modelId 模型id
     * @param modelInfo 模型信息
     */
    @RequestMapping(value="/model/{modelId}/save", method = RequestMethod.PUT)
    public void saveModel(@PathVariable String modelId, ActivitiModelInfo modelInfo) {
         operator.saveModel(modelId, modelInfo);
    }

    @ApiOperation("流程模型列表")
    @GetResource(name = "流程模型列表", path = "/modelListData")
    public ResponseData modelListData( ActiviModelListRequest modelListRequest) {
        PageResult<Model> models = null;
        try {
            models = operator.modelListData(modelListRequest);
        }catch (Exception e) {
            return new ErrorResponseData("holly-d-bpmn","查询流程模型列表错误");
        }
        return new SuccessResponseData(models);
    }

    @ApiOperation("流程模型创建")
    @RequestMapping(name = "流程模型创建", path = "/create")
    public void newModel(NewModelRequest newModelRequest,HttpServletRequest request,HttpServletResponse response) {
        try {
            Model model = operator.newModel(newModelRequest);
            response.sendRedirect(request.getContextPath() + "/activiti/modeler.html?modelId=" + model.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ApiOperation("流程模型删除")
    @GetResource(name = "流程模型删除", path = "/delete/{id}")
    public ResponseData delete(@PathVariable("id")String id) {
        String res = operator.deleteMode(id);
        return new SuccessResponseData(res);
    }

    @ApiOperation("流程模型部署")
    @GetResource(name = "流程模型部署", path = "/deployment/deploy")
    public ResponseData deploy(@RequestParam("id")String id,@RequestParam("routeName") String routeName,@RequestParam("businessTable") String businessTable,@RequestParam("categoryId") String categoryId,@RequestParam("type") Integer type) {

//        String res = operator.deploy(id);
//
//        if (StrUtil.equals(res,"部署成功")) {
//            return new SuccessResponseData(res);
//        } else {
//            return new ErrorResponseData("holly-d-bpmn",res);
//        }
        return operator.deploy2(id,routeName,businessTable,categoryId,type);
    }

    @ApiOperation("根据流程模型id获取流程节点信息")
    @GetResource(name = "根据流程模型id获取流程节点信息", path = "/bpmnmodel/{id}",requiredLogin = false,requiredPermission = false)
    public ResponseData bpmnModelById(@PathVariable("id")String id) {

        List<Map<String, Object>> ans = null;
        try {
            ans= operator.fetchBpmnModelById(id);
        } catch (Exception e) {
            return new ErrorResponseData("95007","根据模型id获取BPMN MODEL出错,id:::"+id);
        }

        return new SuccessResponseData(ans);
    }

    @ApiOperation("根据流程模型id获取流程节点树信息[Ztree]")
    @GetResource(name = "根据流程模型id获取流程节点树信息[Ztree]", path = "/bpmnToZtree/{id}",requiredLogin = false,requiredPermission = false)
    public ResponseData getflowsToZtree(@PathVariable("id")String id) {

        List<Map<String, String>> ans = null;
        try {
            ans= operator.getflowsToZtree(id);
        } catch (Exception e) {
            return new ErrorResponseData("95007","根据模型id获取BPMN MODEL出错,id:::"+id);
        }

        return new SuccessResponseData(ans);
    }

    @ApiOperation("根据流程模型id获取流程节点树信息[VUE&REACT]")
    @GetResource(name = "根据流程模型id获取流程节点树信息[VUE&REACT]", path = "/bpmnToVueOrReactTree/{id}",requiredLogin = false,requiredPermission = false)
    public ResponseData getflowsToVueOrReactTree(@PathVariable("id")String id) {

        List<BpmnModelTreeNode> ans = null;
        try {
            ans= operator.getflowsToVueOrReact(id);
        } catch (Exception e) {
            return new ErrorResponseData("95007","根据模型id获取BPMN MODEL出错,id:::"+id);
        }

        return new SuccessResponseData(ans);
    }






    /**导出部署流程资源*/
    @ApiOperation("流程模型导出")
    @GetResource(name = "流程模型导出", path = "/export")
    public void export(@RequestParam String id,HttpServletResponse response) {
        Map<String,Object> map = operator.export(id);
        String srcName = String.valueOf(map.get("src"));
        InputStream inputStream = (InputStream)map.get("in");
        try {
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(srcName, "UTF-8"));
            byte[] b = new byte[1024];
            int len = -1;
            while ((len = inputStream.read(b, 0, 1024)) != -1) {
                response.getOutputStream().write(b, 0, len);
            }
            response.flushBuffer();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @ApiOperation("高亮实时流程图")
    @GetResource(name = "高亮实时流程图",path = "/getHighlightImg/{id}")
    public void getHighlightImg(@PathVariable String id, HttpServletResponse response) throws Exception{
        Map<String, Object> map = operator.highLight(id);
        InputStream inputStream = (InputStream) map.get("in");
        String picName = String.valueOf(map.get("picName"));
        try {
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(picName, "UTF-8"));
            byte[] b = new byte[1024];
            int len = -1;
            while ((len = inputStream.read(b, 0, 1024)) != -1) {
                response.getOutputStream().write(b, 0, len);
            }
            response.flushBuffer();
        } catch (IOException e) {
            throw new Exception("读取流程图片失败");
        }
    }

    @ApiOperation("查看XML")
    @GetResource(name = "查看XML",path = "/getBpmnXml")
    public void getBpmnXml(HttpServletResponse response,@RequestParam("deploymentId") String deploymentId) {
        try {
            BpmnModel bpmnModel = operator.exportBpmnXml(deploymentId);
            BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
            byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
            ByteArrayInputStream inputStream = new ByteArrayInputStream(bpmnBytes);
            int count = inputStream.available();
            byte[] bytes = new byte[count];
            response.setContentType("text/xml; charset=UTF-8"); //转码
            OutputStream outputStream = response.getOutputStream();
            while (inputStream.read(bytes) != -1) {
                outputStream.write(bytes);
            }
            inputStream.close();
        } catch (Exception e) {
            log.error("查看XML报错");
        }
    }

    @ApiOperation("导出BPMNXML")
    @GetResource(name = "导出BPMNXML",path = "/exportBpmnXml")
    public void exportBpmnXml(HttpServletResponse response,@RequestParam("deploymentId") String deploymentId) {
        response.setContentType("text/html; charset=UTF-8"); //转码
        try {
            BpmnModel bpmnModel = operator.exportBpmnXml(deploymentId);
            BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
            byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
            ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
            String filename = bpmnModel.getMainProcess().getId() + ".bpmn20.xml";
            response.setContentType("application/xml");
            response.setHeader("Content-Disposition", "attachment; filename=" + filename);
            IOUtils.copy(in, response.getOutputStream());  //这句必须放到setHeader下面，否则10K以上的xml无法导出，
            response.flushBuffer();
        } catch (Exception e) {
            log.info("导出失败：modelId="+deploymentId, e);
        }
    }

    @ApiOperation("流程跟踪URL")
    @GetResource(name = "流程跟踪URL",path = "/getTrackUrl/{id}")
    public ResponseData getTrackUrl(@PathVariable String id) {
        String ip = NetWorkUtil.getInet4Address();
        String url = operator.fetchTrackUrl(ip,port,contentPath,id);
        return new SuccessResponseData(url);
    }

}
